package com.gopay.common.util.concurrent;


import com.gopay.common.util.NamedThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.concurrent.*;

/**
 * 超时callable
 * @author ddh02
 * @TimeoutCallable
 * @2017/11/1 9:33  www.gopay.com.cn Inc.All rights reserved.
 */


public abstract class TimeoutCallable<V> implements Callable<V> {

    protected Logger logger ;

    private TimeoutFuture timeoutFuture;

    private void init() {
        logger = LoggerFactory.getLogger(this.getClass());
    }


    public TimeoutCallable(TimeoutFuture timeoutFuture) {
        init();
        this.timeoutFuture = timeoutFuture;
    }

    public abstract V doJob();

    public Object before() {
        logger.info("call  before ...");
        timeoutFuture.setStart(System.currentTimeMillis());
        return null;
    }


    @Override
    public V call() throws Exception {

        before();
        V v = null;
        try {
            v = doJob();
        } catch (Exception e) {
            if (timeoutFuture.getListener() != null) {
                timeoutFuture.getListener().error(e);
            }
        }

        after();
        return v;
    }

    public Object after() {
        logger.info("call  after ...");
        return null;
    }


    public TimeoutFuture getTimeoutFuture() {
        return timeoutFuture;
    }

    public void setTimeoutFuture(TimeoutFuture timeoutFuture) {
        this.timeoutFuture = timeoutFuture;
    }


    static class DemoCall extends TimeoutCallable<Boolean> {

        private int i;

        public DemoCall(TimeoutFuture timeoutFuture, int i) {
            super(timeoutFuture);
            this.i = i;
        }

        @Override
        public Boolean doJob() {

            try {
                logger.info("in " + i);

                try {
                    if (i % 2 == 0) {
                        Thread.sleep(1000);
                    } else {
                        Thread.sleep(7000);
                    }
                } catch (Exception e) {
                    logger.error("中断");
                }

                logger.info(Thread.currentThread().getName() + "___" + new Date().toString() + "--" + i);

                logger.info("out " + i);
            } catch (Exception e) {
                logger.error("", e);
                throw e;
            } finally {

            }
            return true;
        }
    }


    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService monitor = Executors.newSingleThreadScheduledExecutor();
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(2, new NamedThreadFactory("00700mt"));
        System.out.println(new Date() + "start");
        long start = System.currentTimeMillis();

        for (int i = 0; i < 10; i++) {
            TimeoutFuture tf = new TimeoutFuture();
            tf.setListener(new TimeoutFuture.TimeoutFutureListener() {
                @Override
                public void success(Object o) {
                    System.out.println("success===>>>" + o);
                }

                @Override
                public void cancel() {
                    System.out.println("cancel===>>");
                }

                @Override
                public void error(Exception e) {
                    System.out.println("error===>>>" + e);
                }
            });
            Future<?> future = threadPool.submit(new DemoCall(tf, i));
           // timeoutFutureList.add(tf);

            tf.withTimeout(future, 5L, 1L, TimeUnit.SECONDS, monitor);
        }
        System.out.println(new Date() + "=======1");

        Thread.sleep(2000000);
    }
}
